স্প্রিং বুট ক্লায়েন্টে HTTP API কল করতে RestTemplate (Synchronous) এবং WebClient (Asynchronous) দুটি পদ্ধতি ব্যবহার করা হয়।
১. Synchronous Request Handling (RestTemplate)
RestTemplate-এর বৈশিষ্ট্য:
- সিঙ্ক্রোনাস অর্থাৎ মেইন থ্রেডে রিকুয়েস্ট এবং রেসপন্স প্রসেস হয়।
- API কল শেষ না হওয়া পর্যন্ত থ্রেড ব্লক হয়ে থাকে।
- সহজ এবং স্ট্রেটফরওয়ার্ড।
RestTemplate উদাহরণ:
GET Request:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class SyncController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/sync-get")
public String syncGet() {
String url = "https://jsonplaceholder.typicode.com/posts/1";
return restTemplate.getForObject(url, String.class);
}
}
POST Request:
@PostMapping("/sync-post")
public String syncPost() {
String url = "https://jsonplaceholder.typicode.com/posts";
Post post = new Post(1, "My Title", "This is a sample body.");
return restTemplate.postForObject(url, post, String.class);
}
২. Asynchronous Request Handling (WebClient)
WebClient-এর বৈশিষ্ট্য:
- অ্যাসিঙ্ক্রোনাস অর্থাৎ API রিকুয়েস্ট এবং রেসপন্স আলাদা থ্রেডে প্রসেস হয়।
- ইভেন্ট-ড্রিভেন আর্কিটেকচার এবং রিয়াক্টিভ প্রোগ্রামিং সমর্থন করে।
- ব্লকিং অপারেশন ছাড়া দ্রুত রেসপন্স।
WebClient কনফিগারেশন:
WebClient Bean তৈরি:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient(WebClient.Builder builder) {
return builder.build();
}
}
WebClient ব্যবহার:
GET Request (Asynchronous):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class AsyncController {
@Autowired
private WebClient webClient;
@GetMapping("/async-get")
public Mono<String> asyncGet() {
String url = "https://jsonplaceholder.typicode.com/posts/1";
return webClient.get()
.uri(url)
.retrieve()
.bodyToMono(String.class);
}
}
POST Request (Asynchronous):
@PostMapping("/async-post")
public Mono<String> asyncPost() {
String url = "https://jsonplaceholder.typicode.com/posts";
Post post = new Post(1, "My Title", "This is a sample body.");
return webClient.post()
.uri(url)
.bodyValue(post)
.retrieve()
.bodyToMono(String.class);
}
৩. RestTemplate vs WebClient
| Feature | RestTemplate | WebClient |
|---|---|---|
| Threading Model | Blocking | Non-blocking |
| Performance | Slower in high concurrency | Faster and scalable |
| Ease of Use | Simple and familiar API | Modern but slightly complex |
| Use Case | Synchronous applications | Asynchronous/reactive systems |
উদাহরণ: Thread Performance Test
RestTemplate Blocking Example:
@GetMapping("/resttemplate-test")
public String restTemplateTest() {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
restTemplate.getForObject("https://jsonplaceholder.typicode.com/posts/" + i, String.class);
}
long endTime = System.currentTimeMillis();
return "Total time (ms): " + (endTime - startTime);
}
WebClient Non-blocking Example:
@GetMapping("/webclient-test")
public Mono<String> webClientTest() {
long startTime = System.currentTimeMillis();
return Mono.zip(
webClient.get().uri("https://jsonplaceholder.typicode.com/posts/1").retrieve().bodyToMono(String.class),
webClient.get().uri("https://jsonplaceholder.typicode.com/posts/2").retrieve().bodyToMono(String.class)
).map(tuple -> {
long endTime = System.currentTimeMillis();
return "Total time (ms): " + (endTime - startTime);
});
}
উপসংহার:
- যদি আপনার অ্যাপ্লিকেশন ব্লকিং রিকুয়েস্ট ব্যবহার করে, তবে
RestTemplateসেরা সমাধান। - যদি আপনি স্কেলেবল এবং রেসপন্সিভ অ্যাপ্লিকেশন চান, তবে
WebClientব্যবহার করুন। - স্প্রিং-এর ভবিষ্যত সংস্করণে
RestTemplateপরিবর্তেWebClient-কে স্ট্যান্ডার্ড হিসেবে সুপারিশ করা হয়েছে।
Spring Boot ক্লায়েন্ট (RestTemplate, WebClient ইত্যাদি) ব্যবহার করে HTTP রিকোয়েস্ট প্রেরণ করার সময়, আমরা Synchronous বা Asynchronous পদ্ধতিতে কাজ করতে পারি। এই দুটি পদ্ধতির মধ্যে মূল পার্থক্য হলো রিকোয়েস্ট সম্পাদিত হওয়ার সময়কাল এবং প্রক্রিয়ার নিয়ন্ত্রণ।
১. Synchronous Request
- ডেফিনিশন:
Synchronous রিকোয়েস্ট হলো এমন একটি প্রক্রিয়া যেখানে রিকোয়েস্ট প্রেরণের পরে প্রোগ্রাম সম্পূর্ণ রেসপন্স না পাওয়া পর্যন্ত অপেক্ষা করে। এটি ব্লকিং অপারেশন। - বৈশিষ্ট্য:
- ক্লায়েন্ট থ্রেড রেসপন্স না পাওয়া পর্যন্ত অপেক্ষা করে।
- সহজ এবং লজিক বোঝা সহজ।
- ছোট স্কেলের অ্যাপ্লিকেশনের জন্য কার্যকর।
- অপেক্ষার সময় থ্রেড অব্যবহৃত থাকে।
- ব্যবহার:
RestTemplate বা WebClient-এর.block()ব্যবহার করে Synchronous রিকোয়েস্ট করা যায়।
উদাহরণ (RestTemplate):
import org.springframework.web.client.RestTemplate;
public class SynchronousExample {
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
String url = "https://jsonplaceholder.typicode.com/posts/1";
// Synchronous call
String response = restTemplate.getForObject(url, String.class);
System.out.println(response); // রেসপন্স পাওয়ার পর প্রিন্ট করবে
}
}
উদাহরণ (WebClient):
import org.springframework.web.reactive.function.client.WebClient;
public class SynchronousExample {
public static void main(String[] args) {
WebClient webClient = WebClient.create("https://jsonplaceholder.typicode.com");
// Synchronous call using block()
String response = webClient.get()
.uri("/posts/1")
.retrieve()
.bodyToMono(String.class)
.block(); // Blocking call
System.out.println(response); // রেসপন্স পাওয়ার পর প্রিন্ট করবে
}
}
২. Asynchronous Request
- ডেফিনিশন:
Asynchronous রিকোয়েস্ট হলো এমন একটি প্রক্রিয়া যেখানে রিকোয়েস্ট প্রেরণের পর ক্লায়েন্ট থ্রেড রেসপন্স না পাওয়া পর্যন্ত অপেক্ষা করে না। এটি নন-ব্লকিং অপারেশন। - বৈশিষ্ট্য:
- ক্লায়েন্ট থ্রেড রিকোয়েস্ট প্রেরণের পর অবিলম্বে অন্য কাজ করতে পারে।
- বড় স্কেলের এবং উচ্চ কার্যক্ষমতার অ্যাপ্লিকেশনের জন্য কার্যকর।
- রেসপন্স প্রাপ্ত হলে ক্যালব্যাক মেথড বা রিঅ্যাকটিভ স্ট্রিম ব্যবহার করে ডেটা প্রক্রিয়াজাত করা হয়।
- ব্যবহার:
WebClient-এর.bodyToMono()বা.bodyToFlux()ব্যবহার করে Asynchronous রিকোয়েস্ট করা যায়।
উদাহরণ (WebClient):
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class AsynchronousExample {
public static void main(String[] args) {
WebClient webClient = WebClient.create("https://jsonplaceholder.typicode.com");
// Asynchronous call
Mono<String> response = webClient.get()
.uri("/posts/1")
.retrieve()
.bodyToMono(String.class);
// রেসপন্স পাওয়ার পর প্রিন্ট করবে
response.subscribe(res -> System.out.println("Response: " + res));
System.out.println("Request sent, waiting for response...");
}
}
৩. Synchronous এবং Asynchronous এর পার্থক্য
| বৈশিষ্ট্য | Synchronous Request | Asynchronous Request |
|---|---|---|
| কাজের ধরন | ব্লকিং (Blocking) | নন-ব্লকিং (Non-blocking) |
| থ্রেড ব্যবহারের ধরন | একটি থ্রেড কাজ শেষ না হওয়া পর্যন্ত অপেক্ষা করে | থ্রেড অবিলম্বে মুক্ত হয়ে যায় |
| রেসপন্স টাইম | অপেক্ষাকৃত ধীর (থ্রেড ব্লক হওয়ার কারণে) | অপেক্ষাকৃত দ্রুত (নন-ব্লকিং পদ্ধতি) |
| ব্যবহারযোগ্যতা | ছোট স্কেল অ্যাপ্লিকেশন | বড় স্কেল, উচ্চ কার্যক্ষম অ্যাপ্লিকেশন |
| উদাহরণ | RestTemplate, WebClient-এর .block() | WebClient, রিঅ্যাকটিভ স্ট্রিম |
| ডেটা প্রসেসিং | রেসপন্স পাওয়ার পরপর ডেটা প্রক্রিয়াজাত হয় | ক্যালব্যাক বা স্ট্রিম ভিত্তিক প্রক্রিয়া |
৪. কখন কোনটি ব্যবহার করবেন?
- Synchronous Request ব্যবহার করবেন:
- অ্যাপ্লিকেশন ছোট এবং সাধারণ হলে।
- একটি নির্দিষ্ট কাজ সম্পন্ন না হওয়া পর্যন্ত থ্রেড অপেক্ষা করতে পারে।
- ব্লকিং অপারেশন প্রয়োজন হলে।
- Asynchronous Request ব্যবহার করবেন:
- অ্যাপ্লিকেশন বড় এবং স্কেলেবল হলে।
- নেটওয়ার্ক ল্যাটেন্সি কমাতে চাইলে।
- একাধিক রিকোয়েস্ট সমান্তরাল (parallel) প্রক্রিয়াকরণ করতে চাইলে।
- রিঅ্যাকটিভ প্রোগ্রামিং এবং নন-ব্লকিং অপারেশন প্রয়োজন হলে।
উপসংহার
- Synchronous Request হলো সহজ এবং স্ট্রেইট-ফরোয়ার্ড, তবে বড় অ্যাপ্লিকেশন বা উচ্চ কার্যক্ষমতা প্রয়োজন হলে এটি কার্যকর নয়।
- Asynchronous Request বড় স্কেল অ্যাপ্লিকেশনের জন্য উপযুক্ত, বিশেষত যেখানে নন-ব্লকিং অপারেশন এবং রিঅ্যাকটিভ প্রোগ্রামিং প্রয়োজন হয়।
আপনার অ্যাপ্লিকেশনের চাহিদা অনুযায়ী সঠিক পদ্ধতি নির্বাচন করুন। প্রয়োজনে আরও উদাহরণ বা জটিল কনফিগারেশন নিয়ে সাহায্য করতে পারি।
WebClient এর মাধ্যমে Asynchronous Request:
WebClient হলো Spring WebFlux-এর একটি অংশ, যা নন-ব্লকিং এবং রিঅ্যাক্টিভ প্রোগ্রামিং সমর্থন করে। এটি asynchronous request তৈরি করতে ব্যবহৃত হয়।
WebClient এর মাধ্যমে Asynchronous Request এর উদাহরণ:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@RestController
public class WebClientAsyncController {
private final WebClient webClient;
public WebClientAsyncController(WebClient.Builder builder) {
this.webClient = builder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
@GetMapping("/async-webclient")
public Mono<String> fetchAsyncData() {
return webClient.get()
.uri("/posts/1")
.retrieve()
.bodyToMono(String.class); // Asynchronous response
}
}
ব্যাখ্যা:
Mono<String>একটি Reactive স্ট্রিম, যা ডেটা পাওয়ার পর একটি একক ভ্যালু প্রদান করে।retrieve()মেথডটি সার্ভার থেকে ডেটা রিসিভ করে।bodyToMono(String.class)ডেটাকে asynchronous পদ্ধতিতে প্রক্রিয়াজাত করে।
RestTemplate এর মাধ্যমে Asynchronous Request:
RestTemplate নিজে ব্লকিং I/O-এর জন্য ডিজাইন করা, তবে Spring এর AsyncRestTemplate (যা Spring 5 থেকে Deprecated) ব্যবহার করে asynchronous request তৈরি করা সম্ভব। এর বাইরেও Java CompletableFuture ব্যবহার করে RestTemplate এর মাধ্যমে asynchronous request করা যায়।
CompletableFuture ব্যবহার করে Asynchronous Request এর উদাহরণ:
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.CompletableFuture;
@RestController
public class RestTemplateAsyncController {
private final RestTemplate restTemplate;
public RestTemplateAsyncController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Async
@GetMapping("/async-resttemplate")
public CompletableFuture<String> fetchAsyncData() {
return CompletableFuture.supplyAsync(() -> {
String url = "https://jsonplaceholder.typicode.com/posts/1";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
return response.getBody();
});
}
}
ব্যাখ্যা:
@Async:- এই অ্যানোটেশনটি Spring-কে জানায় যে, এটি একটি asynchronous মেথড।
CompletableFuture:- Java 8 এর ফিচার, যা asynchronous প্রোগ্রামিং সমর্থন করে।
supplyAsync():- এটি একটি ব্যাকগ্রাউন্ড থ্রেডে asynchronous কাজ সম্পন্ন করে।
WebClient বনাম RestTemplate এর মাধ্যমে Asynchronous Request:
| ফিচার | WebClient | RestTemplate + CompletableFuture |
|---|---|---|
| ব্লকিং বা নন-ব্লকিং | সম্পূর্ণ নন-ব্লকিং। | মূলত ব্লকিং, তবে CompletableFuture দিয়ে নন-ব্লকিং করা যায়। |
| Reactive Programming | Reactive Streams (Mono এবং Flux) সমর্থন করে। | Reactive Programming সমর্থন করে না। |
| ব্যবহার সহজতা | WebClient দিয়ে Asynchronous Request সহজ। | CompletableFuture ব্যবহারে কোড একটু বেশি জটিল। |
| পারফরম্যান্স | কনকারেন্ট রিকোয়েস্টে পারফরম্যান্স অনেক ভালো। | তুলনামূলকভাবে কম। |
| Spring Future | Spring WebFlux-এর অংশ। | Spring MVC-এর অংশ। |
উপসংহার
- WebClient হল Spring Boot-এ asynchronous এবং non-blocking request-এর জন্য সেরা পছন্দ। এটি reactive এবং modern অ্যাপ্লিকেশনের জন্য কার্যকর।
- RestTemplate ব্লকিং মডেল হলেও CompletableFuture ব্যবহার করে asynchronous request করা যায়। তবে এটি তুলনামূলকভাবে পুরোনো পদ্ধতি।
- নতুন প্রজেক্টে WebClient ব্যবহার করার পরামর্শ দেওয়া হয়, বিশেষত যদি আপনার অ্যাপ্লিকেশন reactive এবং high-concurrency সমর্থন করে।
স্প্রিং বুট ক্লায়েন্টে অ্যাসিনক্রোনাস প্রোগ্রামিং এবং নন-ব্লকিং কলের জন্য CompletableFuture এবং Mono/Flux অত্যন্ত গুরুত্বপূর্ণ। এই দুটি পদ্ধতি পৃথকভাবে কাজ করে, তবে উভয়ই অ্যাসিনক্রোনাস ডেটা প্রসেসিংয়ের জন্য ব্যবহৃত হয়।
১. CompletableFuture এবং এর ব্যবহার
CompletableFuture হলো Java 8-এর একটি ফিচার যা অ্যাসিনক্রোনাস টাস্ক চালানোর জন্য ব্যবহার হয়। এটি ব্লকিং নয় এবং ভবিষ্যতে একটি রেসপন্স রিটার্ন করবে।
CompletableFuture এর প্রাথমিক ব্যবহার:
import java.util.concurrent.CompletableFuture;
public CompletableFuture<String> fetchDataAsync(String url) {
return CompletableFuture.supplyAsync(() -> {
// এখানে HTTP কল বা অন্য কোনো অ্যাসিনক্রোনাস কাজ করুন
return "Response from " + url;
});
}
স্প্রিং বুটে CompletableFuture ব্যবহার:
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class ApiClient {
public CompletableFuture<String> getData(String url) {
return CompletableFuture.supplyAsync(() -> {
// HTTP কল (RestTemplate বা WebClient ব্যবহার করুন)
return "Fetched Data from " + url;
});
}
}
CompletableFuture ব্যবহার করে কল করা:
ApiClient client = new ApiClient();
CompletableFuture<String> futureResponse = client.getData("https://api.example.com/data");
futureResponse.thenAccept(response -> {
System.out.println("Response: " + response);
}).exceptionally(ex -> {
System.err.println("Error occurred: " + ex.getMessage());
return null;
});
২. Mono এবং Flux এবং এর ব্যবহার
Mono এবং Flux হলো Spring WebFlux-এর অংশ, যা রিয়াক্টিভ প্রোগ্রামিং মডেলে কাজ করে।
- Mono: একক অবজেক্ট বা ডেটা রিটার্ন করে।
- Flux: একাধিক ডেটার স্ট্রিম রিটার্ন করে।
Mono ব্যবহার:
import reactor.core.publisher.Mono;
public Mono<String> fetchDataMono(String url) {
return Mono.just("Response from " + url);
}
Flux ব্যবহার:
import reactor.core.publisher.Flux;
public Flux<String> fetchDataFlux() {
return Flux.just("Data1", "Data2", "Data3");
}
WebClient এর সাথে Mono এবং Flux ব্যবহার:
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class ApiClient {
private final WebClient webClient;
public ApiClient(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://api.example.com").build();
}
public Mono<String> getData(String endpoint) {
return this.webClient.get()
.uri(endpoint)
.retrieve()
.bodyToMono(String.class);
}
public Flux<String> getMultipleData(String endpoint) {
return this.webClient.get()
.uri(endpoint)
.retrieve()
.bodyToFlux(String.class);
}
}
Mono এর রেসপন্স প্রসেস করা:
ApiClient client = new ApiClient(WebClient.builder());
client.getData("/data").subscribe(response -> {
System.out.println("Response: " + response);
}, error -> {
System.err.println("Error: " + error.getMessage());
});
৩. CompletableFuture এবং Mono/Flux তুলনা
| বৈশিষ্ট্য | CompletableFuture | Mono/Flux |
|---|---|---|
| মডেল | Imperative | Reactive |
| নন-ব্লকিং | হ্যাঁ | হ্যাঁ |
| অ্যাপ্লিকেশন স্কোপ | Java স্ট্যান্ডার্ড ল্যাঙ্গুয়েজ | Spring WebFlux এবং Reactive |
| ডেটা টাইপ | CompletableFuture | Mono, Flux |
| ডেটা ফ্লো | একক রেসপন্স | একক বা একাধিক রেসপন্স |
| স্ট্রিম সাপোর্ট | নেই | আছে (Reactive Streams) |
৪. CompletableFuture এবং Mono/Flux একসাথে ব্যবহার
Spring অ্যাপ্লিকেশনে CompletableFuture থেকে Mono-তে বা Mono থেকে CompletableFuture-এ রূপান্তর করা যেতে পারে।
CompletableFuture থেকে Mono:
import reactor.core.publisher.Mono;
public Mono<String> convertToMono(CompletableFuture<String> future) {
return Mono.fromFuture(future);
}
Mono থেকে CompletableFuture:
import reactor.core.publisher.Mono;
public CompletableFuture<String> convertToFuture(Mono<String> mono) {
return mono.toFuture();
}
৫. Use Case: মাইক্রোসার্ভিসে অ্যাসিনক্রোনাস কমিউনিকেশন
Example: দুটি API কল নন-ব্লকিং পদ্ধতিতে করা (Mono ব্যবহার):
public Mono<String> callTwoApis() {
Mono<String> api1Response = webClient.get().uri("/api1").retrieve().bodyToMono(String.class);
Mono<String> api2Response = webClient.get().uri("/api2").retrieve().bodyToMono(String.class);
return Mono.zip(api1Response, api2Response, (response1, response2) ->
"Combined Response: " + response1 + ", " + response2
);
}
Example: CompletableFuture দিয়ে সমান্তরাল প্রসেসিং:
public CompletableFuture<String> callTwoApisParallel() {
CompletableFuture<String> api1Future = CompletableFuture.supplyAsync(() -> webClient.get()
.uri("/api1")
.retrieve()
.bodyToMono(String.class)
.block());
CompletableFuture<String> api2Future = CompletableFuture.supplyAsync(() -> webClient.get()
.uri("/api2")
.retrieve()
.bodyToMono(String.class)
.block());
return api1Future.thenCombine(api2Future, (response1, response2) ->
"Combined Response: " + response1 + ", " + response2
);
}
উপসংহার
- Mono/Flux: যখন রিয়াক্টিভ প্রোগ্রামিং প্রয়োজন হয়, যেমন মাইক্রোসার্ভিস বা স্ট্রিম ডেটা প্রসেসিং।
- CompletableFuture: স্ট্যান্ডার্ড Java অ্যাপ্লিকেশনে অ্যাসিনক্রোনাস কাজ পরিচালনা করতে।
স্প্রিং বুট ক্লায়েন্টে এই দুটি প্রযুক্তি ব্যবহার করে অ্যাপ্লিকেশনের স্কেল এবং কর্মক্ষমতা উল্লেখযোগ্যভাবে বৃদ্ধি করা যায়।
Spring Boot-এ WebClient ব্যবহার করে Asynchronous HTTP অনুরোধ প্রক্রিয়া করা হয়। এটি Spring WebFlux-এর অংশ এবং Mono ও Flux ব্যবহার করে রিয়্যাক্টিভ প্রোগ্রামিং এর সুবিধা প্রদান করে। WebClient Spring Boot ক্লায়েন্টে Non-blocking এবং Asynchronous API কল করতে ব্যবহৃত হয়।
Asynchronous Request Handling এর সুবিধা
- Non-blocking I/O:
- অনুরোধ পাঠানোর সময় থ্রেড ব্লক হয় না, ফলে অন্য কাজ একসাথে চালিয়ে যাওয়া যায়।
- Reactive Streams ব্যবহার:
- WebClient
MonoএবংFluxব্যবহার করে ডেটা প্রক্রিয়া করে।
- WebClient
- উচ্চতর পারফরম্যান্স:
- মাইক্রোসার্ভিস আর্কিটেকচারে একাধিক কল একসাথে পরিচালনা করার জন্য এটি কার্যকর।
প্রথমে প্রয়োজনীয় ডিপেন্ডেন্সি যোগ করা
Maven ডিপেন্ডেন্সি:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
উদাহরণ: WebClient দিয়ে Asynchronous Request Handling
১. WebClient Bean তৈরি করা
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
২. Asynchronous GET অনুরোধ
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class UserClient {
private final WebClient webClient;
public UserClient(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public Mono<String> getUserById(int userId) {
return webClient.get()
.uri("/users/{id}", userId)
.retrieve()
.bodyToMono(String.class);
}
}
ব্যবহার:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements CommandLineRunner {
@Autowired
private UserClient userClient;
@Override
public void run(String... args) {
userClient.getUserById(1).subscribe(response -> {
System.out.println("User Data: " + response);
});
}
}
৩. Asynchronous POST অনুরোধ
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class UserClient {
private final WebClient webClient;
public UserClient(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public Mono<String> createUser(String name, String email) {
return webClient.post()
.uri("/users")
.bodyValue(new User(name, email))
.retrieve()
.bodyToMono(String.class);
}
}
ব্যবহার:
userClient.createUser("John Doe", "johndoe@example.com")
.subscribe(response -> {
System.out.println("Created User: " + response);
});
Model Class (User):
public class User {
private String name;
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
// Getters and Setters
}
৪. একাধিক Asynchronous কল একসাথে পরিচালনা করা
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
@Service
public class UserClient {
private final WebClient webClient;
public UserClient(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public Flux<String> getAllUsers() {
return webClient.get()
.uri("/users")
.retrieve()
.bodyToFlux(String.class);
}
}
ব্যবহার:
userClient.getAllUsers()
.subscribe(response -> {
System.out.println("User: " + response);
});
৫. Error Handling সহ Asynchronous কল
public Mono<String> getUserWithErrorHandling(int userId) {
return webClient.get()
.uri("/users/{id}", userId)
.retrieve()
.onStatus(
status -> status.is4xxClientError(),
response -> Mono.error(new RuntimeException("Client Error: " + response.statusCode()))
)
.onStatus(
status -> status.is5xxServerError(),
response -> Mono.error(new RuntimeException("Server Error: " + response.statusCode()))
)
.bodyToMono(String.class)
.doOnError(error -> System.err.println("Error occurred: " + error.getMessage()));
}
ব্যবহার:
userClient.getUserWithErrorHandling(999)
.subscribe(
response -> System.out.println("User: " + response),
error -> System.err.println("Error: " + error.getMessage())
);
ব্যাখ্যা: Reactive এবং Asynchronous Response
- Mono: একক ডেটার জন্য ব্যবহৃত হয়। উদাহরণ:
Mono<String>,Mono<User>. - Flux: একাধিক ডেটার জন্য ব্যবহৃত হয়। উদাহরণ:
Flux<User>. - subscribe(): এটি রেসপন্স প্রক্রিয়াকরণ শুরু করে এবং callback method ব্যবহার করে ডেটা হ্যান্ডেল করে।
উপসংহার
WebClient এর মাধ্যমে Asynchronous এবং Non-blocking HTTP কল করার সুবিধা হলো এটি Spring Boot অ্যাপ্লিকেশনে রিয়্যাক্টিভ প্রোগ্রামিং সরবরাহ করে। এটি মাইক্রোসার্ভিস আর্কিটেকচারে উচ্চতর পারফরম্যান্স এবং থ্রেড ব্যবস্থাপনায় সহায়তা করে। উদাহরণগুলো বাস্তবায়ন করলে ক্লায়েন্ট এবং সার্ভারের মধ্যে কার্যকর এবং স্কেলেবল যোগাযোগ নিশ্চিত হয়।
Read more